package service

import (
	"fmt"
	"log"
	"os/exec"
	"strings"
	"sync"
	"time"

	"github.com/robfig/cron/v3"
	"gorm.io/gorm"

	"crongo/internal/model"
)

// TaskService 任务服务
type TaskService struct {
	db    *gorm.DB
	tasks map[uint]*model.Task
	crons map[uint]*cron.Cron
	mu    sync.RWMutex
}

// NewTaskService 创建任务服务
func NewTaskService(db *gorm.DB) *TaskService {
	return &TaskService{
		db:    db,
		tasks: make(map[uint]*model.Task),
		crons: make(map[uint]*cron.Cron),
	}
}

// executeTask 执行任务并记录输出
func (s *TaskService) executeTask(task *model.Task) (string, error) {
	startTime := time.Now()

	// 创建日志记录
	taskLog := &model.TaskLog{
		TaskID:    task.ID,
		StartTime: startTime,
	}

	// 保存日志记录以获取ID
	if err := s.db.Create(taskLog).Error; err != nil {
		log.Printf("创建任务日志记录失败: %v", err)
		return "", err
	}

	// 执行命令
	cmd := exec.Command("sh", "-c", task.Command)
	output, err := cmd.CombinedOutput()
	endTime := time.Now()

	// 更新日志记录
	updates := map[string]interface{}{
		"end_time": endTime,
		"duration": endTime.Sub(startTime),
		"success":  err == nil,
		"output":   string(output),
	}
	if err != nil {
		updates["error"] = err.Error()
	}

	// 更新日志记录
	if err := s.db.Model(taskLog).Updates(updates).Error; err != nil {
		log.Printf("更新任务日志记录失败: %v", err)
	}

	// 更新任务的最后执行时间
	if err := s.db.Model(task).Update("last_run_time", startTime).Error; err != nil {
		log.Printf("更新任务最后执行时间失败: %v", err)
	}

	return string(output), err
}

// StartTask 启动任务
func (s *TaskService) StartTask(task *model.Task) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	// 检查任务状态
	if task.Status != 1 {
		return fmt.Errorf("任务未启用")
	}

	// 检查任务是否已经在运行
	if _, exists := s.crons[task.ID]; exists {
		return fmt.Errorf("任务已在运行")
	}

	// 创建新的定时任务
	cron := cron.New(cron.WithSeconds())
	cronExpr := task.CronExpr
	if len(strings.Fields(cronExpr)) == 5 {
		cronExpr = "0 " + cronExpr // 在开头添加0秒，禁止秒级任务
	} else {
		fields := strings.Fields(cronExpr)
		fields[0] = "0"
		cronExpr = strings.Join(fields, " ")
	}

	_, err := cron.AddFunc(cronExpr, func() {
		s.executeTask(task)
	})
	if err != nil {
		return fmt.Errorf("添加定时任务失败: %v", err)
	}

	// 启动定时任务
	cron.Start()

	// 保存任务和定时器
	s.tasks[task.ID] = task
	s.crons[task.ID] = cron

	return nil
}

// StopTask 停止任务
func (s *TaskService) StopTask(taskID uint) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	cron, exists := s.crons[taskID]
	if !exists {
		return fmt.Errorf("任务未运行")
	}

	// 停止定时任务
	cron.Stop()

	// 删除任务和定时器
	delete(s.tasks, taskID)
	delete(s.crons, taskID)

	return nil
}

// StartAllTasks 启动所有已启用的任务
func (s *TaskService) StartAllTasks() error {
	var tasks []model.Task
	if err := s.db.Where("status = ?", 1).Find(&tasks).Error; err != nil {
		return fmt.Errorf("查询任务失败: %v", err)
	}

	// 先停止所有任务
	s.StopAllTasks()

	// 清理任务映射
	s.mu.Lock()
	s.tasks = make(map[uint]*model.Task)
	s.crons = make(map[uint]*cron.Cron)
	s.mu.Unlock()

	for i := range tasks {
		task := &tasks[i]
		if err := s.StartTask(task); err != nil {
			log.Printf("启动任务[%d]失败: %v", task.ID, err)
			// 不返回错误，继续启动其他任务
		}
	}

	return nil
}

// StopAllTasks 停止所有任务
func (s *TaskService) StopAllTasks() {
	s.mu.Lock()
	defer s.mu.Unlock()

	for taskID, cron := range s.crons {
		cron.Stop()
		delete(s.tasks, taskID)
		delete(s.crons, taskID)
	}
}

// validateCronExpr 验证cron表达式
func (s *TaskService) validateCronExpr(expr string) error {
	fields := strings.Fields(expr)
	if len(fields) != 5 {
		return fmt.Errorf("cron表达式必须是5个字段")
	}

	// 验证表达式是否有效
	parser := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)
	_, err := parser.Parse(expr)
	if err != nil {
		return fmt.Errorf("无效的cron表达式: %v", err)
	}

	return nil
}

// CreateTask 创建新任务
func (s *TaskService) CreateTask(task *model.Task) error {
	if err := s.validateCronExpr(task.CronExpr); err != nil {
		return err
	}
	return s.db.Create(task).Error
}

// UpdateTask 更新任务
func (s *TaskService) UpdateTask(task *model.Task) error {
	// 获取原有任务
	var oldTask model.Task
	if err := s.db.First(&oldTask, task.ID).Error; err != nil {
		return fmt.Errorf("任务不存在: %v", err)
	}

	// 如果更新了cron表达式，则验证
	if task.CronExpr != "" {
		if err := s.validateCronExpr(task.CronExpr); err != nil {
			return err
		}
	} else {
		task.CronExpr = oldTask.CronExpr
	}

	// 停止原有任务
	s.StopTask(task.ID)

	// 更新任务
	if err := s.db.Model(&oldTask).Updates(task).Error; err != nil {
		return err
	}

	// 如果任务是启用状态，则重新启动
	if task.Status == 1 || (task.Status == 0 && oldTask.Status == 1) {
		return s.StartTask(&oldTask)
	}
	return nil
}

// ListTasks 列出任务
func (s *TaskService) ListTasks(groupName string) ([]model.Task, error) {
	var tasks []model.Task
	query := s.db
	if groupName != "" {
		query = query.Where("group_name = ?", groupName)
	}
	err := query.Find(&tasks).Error
	return tasks, err
}

// GetTaskGroups 获取所有任务组
func (s *TaskService) GetTaskGroups() ([]string, error) {
	var groups []string
	err := s.db.Model(&model.Task{}).Distinct().Pluck("group_name", &groups).Error
	return groups, err
}

// DeleteTask 删除任务
func (s *TaskService) DeleteTask(id uint) error {
	// 先停止任务
	s.StopTask(id)

	// 从数据库中删除任务
	if err := s.db.Delete(&model.Task{}, id).Error; err != nil {
		return fmt.Errorf("删除任务失败: %v", err)
	}

	// 删除任务相关的日志记录
	if err := s.db.Where("task_id = ?", id).Delete(&model.TaskLog{}).Error; err != nil {
		log.Printf("删除任务日志失败: %v", err)
	}

	return nil
}
